/**
 * 控件、插件
 * by ZL 2018/11/27 新增
 */
import zrender from 'zrender';
import utils from './utils';
import fecha from '@/utils/date';
const graphicClock = {
  group: null,
  timer: null,
  params: {
    x: 0,
    y: 0,
    width: 60,
    height: 60,
    showWeek: true,
    showDate: true,
    showTime: true,
    weekColor: 'rgb(0,0,0)',
    dateColor: 'rgb(0,0,0)',
    timeColor: 'rgb(0,0,0)'
  },
  render (params) {
    Object.assign(this.params, params);
    const posInfo = this._parsePosition();

    this.group = new zrender.Group({
      position: [this.params.x, this.params.y]
    });

    this._renderBorder(posInfo);
    this._renderTicks(posInfo);
    this._renderPointer(posInfo);
    return this.group;
  },
  _renderBorder (posInfo) {
    const bgCircle = new zrender.Circle({
      shape: posInfo,
      style: {
        // fill: 'rgb(255,0,0)'
        fill: new zrender.LinearGradient(1, 0, 0, 1, [
          {
            offset: 0.5,
            color: '#f00'
          },
          {
            offset: 1,
            color: '#fff'
          }
        ])
      }
    });
    const inCircle = new zrender.Circle({
      shape: {
        cx: posInfo.cx,
        cy: posInfo.cy,
        r: posInfo.r - 10
      },
      style: {
        fill: new zrender.LinearGradient(0, 0, 1, 1, [
          {
            offset: 0,
            color: '#fff'
          },
          {
            offset: 1,
            color: '#f66'
          }
        ])
      }
    });
    const inRing = new zrender.Circle({
      shape: {
        cx: posInfo.cx,
        cy: posInfo.cy,
        r: posInfo.r - 20
      },
      style: {
        stroke: '#000',
        fill: '#fff',
        lineWidth: 2,
        strokeNoScale: true
      }
    });
    this.group.add(bgCircle);
    this.group.add(inCircle);
    this.group.add(inRing);
  },
  _renderTicks (posInfo) {
    const hStep = Math.PI / 6;
    const mStep = Math.PI / 30;
    const rPin = posInfo.r - 30;
    const rText = posInfo.r - 60;
    for (let i = 0; i < 12; i++) {
      const unitX = Math.cos(hStep * i);
      const unitY = Math.sin(hStep * i);
      const hourPin = new zrender.Circle({
        shape: {
          cx: posInfo.cx + unitX * rPin,
          cy: posInfo.cy + unitY * rPin,
          r: 5
        },
        style: {
          fill: '#000'
        }
      });
      const Hour = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
      const hourText = new zrender.Text({
        style: {
          text: Hour[i],
          textFill: '#000',
          font: '40px sans-serif',
          textAlign: 'center',
          textVerticalAlign: 'middle'
        },
        position: [
          posInfo.cx + unitX * rText,
          posInfo.cy + unitY * rText
        ]
      });
      this.group.add(hourPin);
      this.group.add(hourText);
    }
    for (let j = 0; j < 60; j++) {
      const unitX = Math.cos(mStep * j);
      const unitY = Math.sin(mStep * j);
      const minPin = new zrender.Line({
        shape: {
          x1: posInfo.cx + unitX * (rPin + 4),
          y1: posInfo.cy + unitY * (rPin + 4),
          x2: posInfo.cx + unitX * (rPin - 5),
          y2: posInfo.cy + unitY * (rPin - 5)
        },
        style: {
          stroke: '#000',
          lineWidth: 2,
          strokeNoScale: true
        }
      });
      this.group.add(minPin);
    }
  },
  _renderPointer (posInfo) {
    const ClockPointer = zrender.Path.extend({
      type: 'ClockPointer',
      shape: {
        angle: 0,
        width: 10,
        r: 10,
        x: 0,
        y: 0
      },
      buildPath (ctx, shape) {
        const mathCos = Math.cos;
        const mathSin = Math.sin;

        const r = shape.r;
        const width = shape.width;
        let angle = shape.angle;
        const x = shape.x - mathCos(angle) * width * (width >= r / 3 ? 1 : 2);
        const y = shape.y - mathSin(angle) * width * (width >= r / 3 ? 1 : 2);

        angle = shape.angle - Math.PI / 2;
        ctx.moveTo(x, y);
        ctx.lineTo(
          shape.x + mathCos(angle) * width,
          shape.y + mathSin(angle) * width
        );
        ctx.lineTo(
          shape.x + mathCos(shape.angle) * r,
          shape.y + mathSin(shape.angle) * r
        );
        ctx.lineTo(
          shape.x - mathCos(angle) * width,
          shape.y - mathSin(angle) * width
        );
        ctx.lineTo(x, y);
      }
    });
    const hourPointer = new ClockPointer({
      shape: {
        width: 16,
        x: posInfo.cx,
        y: posInfo.cy,
        r: posInfo.r - 100
      },
      style: {
        fill: '#0f0f0f'
      }
    });
    const minutePointer = new ClockPointer({
      shape: {
        width: 13,
        x: posInfo.cx,
        y: posInfo.cy,
        r: posInfo.r - 60
      }
    });
    const secondPointer = new ClockPointer({
      shape: {
        width: 10,
        x: posInfo.cx,
        y: posInfo.cy,
        r: posInfo.r - 25
      },
      style: {
        fill: '#f00'
      }
    });
    const centerDot = new zrender.Circle({
      shape: {
        cx: posInfo.cx,
        cy: posInfo.cy,
        r: 6
      },
      style: {
        stroke: '#fff',
        fill: '#f00',
        lineWidth: 1,
        strokeNoScale: true
      }
    });
    const step = Math.PI / 30;
    const clockAction = () => {
      const now = new Date();
      const second = now.getSeconds();
      const minute = now.getMinutes() + second / 60;
      const hour = now.getHours() + minute / 60;
      const secAngle = second * step - Math.PI / 2;
      const minAngle = minute * step - Math.PI / 2;
      const hourAngle = hour * step * 5 - Math.PI / 2;
      secondPointer.attr({ shape: { angle: secAngle } });
      minutePointer.attr({ shape: { angle: minAngle } });
      hourPointer.attr({ shape: { angle: hourAngle } });
      this.timer = setTimeout(clockAction, 1000);
    };
    clockAction();
    this.group.add(hourPointer);
    this.group.add(minutePointer);
    this.group.add(secondPointer);
    this.group.add(centerDot);
  },
  _parsePosition () {
    const size = Math.min(this.params.width, this.params.height);
    const r = size / 2;
    return {
      cx: this.params.width / 2,
      cy: this.params.height / 2,
      r: r
    };
  }
};
export default {
  textClockTimer: null,
  plugClock (xmlNode) {
    const type = utils.getAttribute(xmlNode, 'type', 'int');
    const x = utils.getAttribute(xmlNode, 'x', 'float');
    const y = utils.getAttribute(xmlNode, 'y', 'float');
    const width = utils.getAttribute(xmlNode, 'w', 'float');
    const height = utils.getAttribute(xmlNode, 'h', 'float');
    // 数字时钟
    if (type === 1) {
      const Text = new zrender.Text({
        style: {
          text: fecha.format(Date.now(), utils.getAttribute(xmlNode, 'format')),
          textFill: utils.getAttribute(xmlNode, 'color', 'rgb'),
          font: '20px 宋体',
          textPadding: [0, 5]
        },
        position: [x, y]
      });
      const clockAction = () => {
        Text.attr({
          style: {
            text: fecha.format(Date.now(), utils.getAttribute(xmlNode, 'format'))
          }
        });
        this.textClockTimer = setTimeout(clockAction, 1000);
      };

      const bound = Text.getBoundingRect();
      const scale = width / bound.width;
      Text.attr({
        scale: [scale, scale]
      });

      clockAction();

      return Text;
    } else {
      const Graph = graphicClock.render({
        x,
        y,
        width,
        height,
        showWeek: utils.getAttribute(xmlNode, 'showWeek', 'bool2'),
        showDate: utils.getAttribute(xmlNode, 'showDate', 'bool2'),
        showTime: utils.getAttribute(xmlNode, 'showTime', 'bool2'),
        weekColor: utils.getAttribute(xmlNode, 'weekColor', 'rgb'),
        dateColor: utils.getAttribute(xmlNode, 'dateColor', 'rgb'),
        timeColor: utils.getAttribute(xmlNode, 'timeColor', 'rgb')
      });
      return Graph;
    }
  },
  disposeTimer () {
    this.textClockTimer && clearTimeout(this.textClockTimer);
    graphicClock.timer && clearTimeout(graphicClock.timer);
  }
};
